2025-10-01
问题是这样的,在喵喵CRM权限管理模块里,可以修改用户的角色。
但是用户编辑时候,点开角色复选框,选择角色,确认后,用户的角色并没有变化。排查了后端问题之后,初步判断问题应该就是在前端。

因为个人没有系统学习uni-app,主要是AI在写,我来提修改意见,所以这个bug的修复非常折磨。在经历了Gemini和GPT双双折戟后,颇为郁闷。大晚上纠结半天,睡不着,越想越不对,这个问题明明不严重,怎么可能解决不了呢?遂亲自上手,来整体梳理一下。
首先入口代码如下,调用了一个openRoleMultiPicker
<view class="picker-value-display" @click="openRoleMultiPicker">
{{ userSelectedGroupNames.length ? userSelectedGroupNames.join(', ') : '请选择角色' }}
</view>
我们来看下openRoleMultiPicker
// 打开多选角色选择器
openRoleMultiPicker() {
this.$refs.roleMultiPicker.open();
},
打开自定义的 user-role-multi-picker 组件。这个组件是独立出去写得,等下在排查,我觉得问题在确认的接收那儿。我们先看下监听代码:
<user-role-multi-picker
ref="roleMultiPicker"
:value="userFormData.groups_write"
:options="availableGroups"
title="选择用户角色"
@change="onRoleMultiPickerChange"
></user-role-multi-picker>
也就是说,user-role-multi-picker 子组件在确认选择时,应该发送一个 change 事件,并传回,change事件代码如下:
onRoleMultiPickerChange(selectedIds) {
const normalized = Array.isArray(selectedIds)
? selectedIds.map(v => Number(v))
: [];
this.userFormData.groups_write = normalized;
},
这里接收传回来的 selectedIds,存进 userFormData.groups_write。然后有个计算,确认后表单现实的如下:
userSelectedGroupNames() {
return (this.userFormData.groups_write || [])
.map(id => {
const group = this.availableGroups.find(g => String(g.id) === String(id));
return group ? group.name : '';
})
.filter(Boolean);
},
考虑到数据库在修改后同样没有更新,所以初步判断是存进 userFormData.groups_write这儿可能就出了问题,很有可能是数据格式的问题。
上述代码不太明白,但是好歹功能是清楚了。如果是数据格式出了问题,大概率是存进 userFormData.groups_write是,不认或者识别错误。这儿先贴一个示例,也就是用户数据到底什么样:
{
"id": 1,
"username": "13989",
"email": "1398943200@qq.com",
"first_name": "小阳",
"last_name": "沈",
"groups_read": [
{
"id": 1,
"name": "管理员"
}
]
},
当然,这是GET的数据格式。但是实际上写入的是group_write,PATCH 示例数据如下:
{
"groups_write": [1]
}
所以,两种可能,第一种是读的时候是groups_read,写的时候是groups_write,可能传递的参数名不一样,所以获取不了。当然,上述仅限本人粗浅的小白理解。继续往下排查,看看情况。第二种是写个格式错了,比如单纯是1,而不是[1]。
测试了一下,不是上述两种情况。不过在输出数据时候,发现一个很有趣的点,onRoleMultiPickerChange 被触发两轮,而第一次触发时返回的数是对的,[2],但是第二次不知道怎么回事,获取了一个很异常的东西。
02:19:47.397 原始参数: [ 2 ] 类型: object at pages\permission\permission.uvue:335
02:19:47.397 原始参数: [ 2 ] 类型: object at pages\permission\permission.uvue:335
02:19:47.397 原始参数: [ 2 ] 类型: object at pages\permission\permission.uvue:335
02:19:47.397 转换值: 2 -> 2 at pages\permission\permission.uvue:339
02:19:47.397 转换值: 2 -> 2 at pages\permission\permission.uvue:339
02:19:47.397 转换值: 2 -> 2 at pages\permission\permission.uvue:339
02:19:47.408 转换结果: [ 2 ] at pages\permission\permission.uvue:344
02:19:47.408 转换结果: [ 2 ] at pages\permission\permission.uvue:344
02:19:47.408 转换结果: [ 2 ] at pages\permission\permission.uvue:344
02:19:47.408 调用堆栈 at pages\permission\permission.uvue:345
02:19:47.408 调用堆栈 at pages\permission\permission.uvue:345
02:19:47.408 调用堆栈 at pages\permission\permission.uvue:345
02:19:47.408 console.groupEnd at pages\permission\permission.uvue:346
02:19:47.408 console.groupEnd at pages\permission\permission.uvue:346
02:19:47.408 console.groupEnd at pages\permission\permission.uvue:346
02:19:47.408 onRoleMultiPickerChange 触发 at pages\permission\permission.uvue:334
02:19:47.408 onRoleMultiPickerChange 触发 at pages\permission\permission.uvue:334
02:19:47.408 onRoleMultiPickerChange 触发 at pages\permission\permission.uvue:334
02:19:47.420 原始参数: [UTSJSONObject2] {show: false, type: "center"} 类型: object at pages\permission\permission.uvue:335
02:19:47.420 原始参数: [UTSJSONObject2] {show: false, type: "center"} 类型: object at pages\permission\permission.uvue:335
02:19:47.420 原始参数: [UTSJSONObject2] {show: false, type: "center"} 类型: object at pages\permission\permission.uvue:335
02:19:47.420 转换结果: [ ... ] at pages\permission\permission.uvue:344
02:19:47.420 转换结果: [ ... ] at pages\permission\permission.uvue:344
02:19:47.420 转换结果: [ ... ] at pages\permission\permission.uvue:344
02:19:47.420 调用堆栈 at pages\permission\permission.uvue:345
02:19:47.420 调用堆栈 at pages\permission\permission.uvue:345
02:19:47.420 调用堆栈 at pages\permission\permission.uvue:345
问了下GPT,onRoleMultiPickerChange 被 触发了两次:
一次是 UserRoleMultiPicker 子组件选择完返回的 [2](正常)
第二次是 uni-popup 关闭的时候,冒泡又触发了一次 @change,参数变成了 {show: false, type: 'center'} 这种对象,结果代码里还当数组去处理 → 就把数据冲掉了。
TMD、TMD、TMD,为什么有这么傻逼的事情!!!!现在凌晨两点四十分,太棒了。
最后onRoleMultiPickerChange 加入一个判断,非常规数值不用管,就解决问题了:
if (!Array.isArray(selectedIds)) {
return;
}